package master

import (
	"encoding/json"
	"gitee.com/zhengjianfeng/crontab/common"
	"net"
	"net/http"
	"strconv"
	"time"
)

var (
	// 单例对象
	G_apiServer *ApiServer
)

// 任务的HTTP接口
type ApiServer struct {
	HttpServer *http.Server
}

// 保存任务接口
// POST job={"name","job1","command":"echo hello","cronExpr":"* * * * *"}
func handleJobSave(resp http.ResponseWriter, req *http.Request) {
	var (
		err     error
		postJob string
		job     common.Job
		oldJob  *common.Job
		bytes   []byte
	)
	// 1、解析POST表单
	if err = req.ParseForm(); err != nil {
		goto ERR
	}

	// 2、取表单中的job字段
	postJob = req.PostForm.Get("job")

	// 3、反序列化job
	if err = json.Unmarshal([]byte(postJob), &job); err != nil {
		goto ERR
	}

	// 4、保存到etcd
	if oldJob, err = G_jobMgr.SaveJob(&job); err != nil {
		goto ERR
	}
	// 5、返回正常应答{"errno":0,"msg":"","data":{....}}
	if bytes, err = common.BuildResponse(1, "success", oldJob); err != nil {
		goto ERR
	}
	resp.Write(bytes)
	return

	// 任务保存到etcd中
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
	return
}

// 删除任务接口
// 提交一个请求 POST /job/delete name=job1
func handJobDelete(resp http.ResponseWriter, req *http.Request) {
	var (
		err    error
		name   string
		oldJob *common.Job
		bytes  []byte
	)

	// POST a=1&b=2&c=3
	if err = req.ParseForm(); err != nil {
		goto ERR
	}

	// 获取删除的任务名
	name = req.PostForm.Get("name")

	// 删除任务
	if oldJob, err = G_jobMgr.DeleteJob(name); err != nil {
		goto ERR
	}

	// 正常应答
	if bytes, err = common.BuildResponse(0, "success", oldJob); err != nil {
		goto ERR
	}

	resp.Write(bytes)
	return

ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
	return
}

// 获取所有crontab任务
func handJobList(resp http.ResponseWriter, req *http.Request) {
	//
	var (
		jobList []*common.Job
		err     error
		bytes   []byte
	)
	if jobList, err = G_jobMgr.ListJob(); err != nil {
		goto ERR
	}

	// 返回正常应答
	if bytes, err = common.BuildResponse(0, "success", jobList); err != nil {
		goto ERR
	}

	resp.Write(bytes)
	return

ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
	return
}

// 强制杀死某个任务
func handJobKill(resp http.ResponseWriter, req *http.Request) {

	var (
		bytes []byte
		err   error
		name  string
	)

	// POST a=1&b=2&c=3
	if err = req.ParseForm(); err != nil {
		goto ERR
	}

	// 获取删除的任务名
	name = req.PostForm.Get("name")

	// 杀死任务
	if err = G_jobMgr.KillJob(name); err != nil {
		return
	}

	// 返回正常应答
	if bytes, err = common.BuildResponse(0, "success", nil); err != nil {
		goto ERR
	}

	resp.Write(bytes)
	return

ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
	return
}

// 查询任务日志
func handleJobLog(resp http.ResponseWriter, req *http.Request) {
	var (
		bytes      []byte
		err        error
		name       string // 任务名字
		skipParam  string // 从第几条开始
		limitParam string // 返回多少条
		skip       int
		limit      int
		logArr     []*common.JobLog
	)

	// 解析get参数
	if err = req.ParseForm(); err != nil {
		goto ERR
	}

	// 获取请求参数 /job/log?name=job10&skip=0&limit=10
	name = req.Form.Get("name")
	skipParam = req.Form.Get("skip")
	limitParam = req.Form.Get("limit")
	if skip, err = strconv.Atoi(skipParam); err != nil {
		skip = 0
	}

	if limit, err = strconv.Atoi(limitParam); err != nil {
		limit = 20
	}

	if logArr, err = G_logMgr.ListLog(name, skip, limit); err != nil {
		goto ERR
	}

	// 正常应答
	if bytes, err = common.BuildResponse(0, "success", logArr); err != nil {
		goto ERR
	}

	resp.Write(bytes)

	return
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
	return
}

// 获取健康worker节点列表
func handleWorkerList(resp http.ResponseWriter, req *http.Request) {

	var (
		bytes     []byte
		err       error
		workerArr []string
	)

	if workerArr, err = G_workerMgr.ListWorkers(); err != nil {
		goto ERR
	}

	// 正常应答
	if bytes, err = common.BuildResponse(0, "success", workerArr); err != nil {
		goto ERR
	}

	resp.Write(bytes)

	return
ERR:
	if bytes, err = common.BuildResponse(-1, err.Error(), nil); err == nil {
		resp.Write(bytes)
	}
	return
}

// 初始化事务
func InitApiServer() (err error) {
	// 配置路由
	var (
		mux           *http.ServeMux
		listener      net.Listener
		httpServer    *http.Server
		staticDir     http.Dir     // 静态文件根目录
		staticHandler http.Handler // 静态文件的HTTP回调
	)

	// 配置路由
	mux = http.NewServeMux()
	mux.HandleFunc("/job/save", handleJobSave)
	mux.HandleFunc("/job/delete", handJobDelete)
	mux.HandleFunc("/job/list", handJobList)
	mux.HandleFunc("/job/kill", handJobKill)
	mux.HandleFunc("/job/log", handleJobLog)
	mux.HandleFunc("/worker/list", handleWorkerList)

	// 静态文件目录
	staticDir = http.Dir(G_config.WebRoot)
	staticHandler = http.FileServer(staticDir)
	mux.Handle("/", http.StripPrefix("/", staticHandler))

	// 启动TCP监听
	if listener, err = net.Listen("tcp", ":"+strconv.Itoa(G_config.ApiPoint)); err != nil {
		return err
	}

	// 启动一个HTTP服务
	httpServer = &http.Server{
		ReadHeaderTimeout: time.Duration(G_config.ApiReadTimeout) * time.Millisecond,
		WriteTimeout:      time.Duration(G_config.ApiWriteTimeout) * time.Millisecond,
		Handler:           mux,
	}

	// 赋值单例
	G_apiServer = &ApiServer{
		HttpServer: httpServer,
	}

	// 启动了服务
	go httpServer.Serve(listener)

	return
}
